﻿//------------------------------------------------------------------------------
// ╭─────────────────────────────╮
// │ ╭─╮     ╭─╮              TM │   ╠═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╣
// │ │ │     │ │                 │                                           ☺  
// │ │ ╰───╮ │ │ ╭─────╮ ╭─────╮ │     Name:Wedn.Net 数据库访问基类     ♮ ♪ ♩
// │ │ ╭─╮ │ │ │ │ ╭─╮ │ │ ╭─╮ │ │                                    ♫ ♭      
// │ │ ╰─╯ │ │ │ │ ╰─╯ │ │ ╰─╯ │ │     Author:iceStone               ♬ ♪       
// │ └─────╯ └─╯ ╰─────╯ ╰───╮ │ │     Chinese:汪磊                              
// │                     ┌───╯ │ │                                              
// │                     ╰─────╯ │   ╠═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╬═╣
// ╰─────────────────────────────╯                                              
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace Wedn.Net.DAL
{
    /// <summary>
    /// 数据库访问基类
    /// </summary>
    /// <typeparam name="T">表实体类型</typeparam>
    public class BaseDAO<T> where T : class, new()
    {
        /// <summary>
        /// 数据库实体操作上下文(线程内实例唯一)
        /// </summary>
        private DbContext _dbContext { get { return Factory.GetCurrentDbContext(); } }
        //private readonly DbContext _dbContext = Factory.GetCurrentDbContext();
        //DataModelContainer dbContext = new DataModelContainer();
        /// <summary>
        /// 数据集
        /// </summary>
        public DbSet<T> DbSet { get { return _dbContext.Set<T>(); } }
        /// <summary>
        /// 向数据库中插入一条数据
        /// </summary>
        /// <param name="entity">要插入的实体</param>
        /// <returns>当前实体</returns>
        public virtual T Insert(T entity)
        {
            _dbContext.Set<T>().Add(entity);
            //_dbContext.Entry<T>(entity).State = EntityState.Added;
            //_dbContext.SaveChanges();
            return entity;
        }

        /// <summary>
        /// 向数据库中插入一条数据
        /// </summary>
        /// <param name="entity">要插入的实体</param>
        /// <param name="commit">是否提交到数据库</param>
        /// <returns>当前实体</returns>
        public virtual T Insert(T entity, bool commit)
        {
            _dbContext.Set<T>().Add(entity);
            if (commit)
                _dbContext.SaveChanges();
            return entity;
        }

        /// <summary>
        /// 向数据库中插入多条数据
        /// </summary>
        /// <param name="entitys">要插入的实体</param>
        /// <returns>当前实体</returns>
        public virtual IList<T> Insert(params T[] entitys)
        {
            foreach (var entity in entitys)
            {
                _dbContext.Set<T>().Add(entity);
                //_dbContext.Entry<T>(entity).State = EntityState.Added;
            }
            //_dbContext.SaveChanges();
            return entitys;
        }

        /// <summary>
        /// 向数据库中插入多条数据
        /// </summary>
        /// <param name="commit">是否提交到数据库</param>
        /// <param name="entitys">要插入的实体</param>
        /// <returns>当前实体</returns>
        public virtual IList<T> Insert(bool commit, params T[] entitys)
        {
            foreach (var entity in entitys)
            {
                _dbContext.Set<T>().Add(entity);
            }
            if (commit)
                _dbContext.SaveChanges();
            return entitys;
        }

        /// <summary>
        /// 删除数据库中的一条数据
        /// </summary>
        /// <param name="entity">要删除的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(T entity)
        {
            //_dbContext.Set<T>().Remove(entity);
            _dbContext.Entry(entity).State = System.Data.EntityState.Deleted;
            //return _dbContext.SaveChanges();
            return 1;
        }

        /// <summary>
        /// 删除数据库中的一条数据
        /// </summary>
        /// <param name="entity">要删除的实体</param>
        /// <param name="commit">是否提交到数据库</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(T entity, bool commit)
        {
            _dbContext.Entry(entity).State = System.Data.EntityState.Deleted;
            return commit ? _dbContext.SaveChanges() : 1;
        }

        /// <summary>
        /// 批量删除数据库中多条数据
        /// </summary>
        /// <param name="ids">要删除的实体Id</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(params int[] ids)
        {
            foreach (int id in ids)
            {
                _dbContext.Set<T>().Remove(_dbContext.Set<T>().Find(id));
            }
            //return _dbContext.SaveChanges();
            return ids.Length;
        }

        /// <summary>
        /// 批量删除数据库中多条数据
        /// </summary>
        /// <param name="commit">是否提交到数据库</param>
        /// <param name="ids">要删除的实体Id</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Delete(bool commit, params int[] ids)
        {
            foreach (int id in ids)
            {
                _dbContext.Set<T>().Remove(_dbContext.Set<T>().Find(id));
            }
            return commit ? _dbContext.SaveChanges() : ids.Length;
        }

        /// <summary>
        /// 更新数据库中的一个实体
        /// </summary>
        /// <param name="entity">更新的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(T entity)
        {
            _dbContext.Entry(entity).State = System.Data.EntityState.Modified;
            //return _dbContext.SaveChanges();
            return 1;
        }

        /// <summary>
        /// 更新数据库中的一个实体
        /// </summary>
        /// <param name="entity">更新的实体</param>
        /// <param name="commit">是否提交到数据库</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(T entity, bool commit)
        {
            _dbContext.Entry(entity).State = System.Data.EntityState.Modified;
            return commit ? _dbContext.SaveChanges() : 1;
        }

        /// <summary>
        /// 更新数据库中的多个实体
        /// </summary>
        /// <param name="entitys">更新的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(params T[] entitys)
        {
            foreach (var entity in entitys)
            {
                _dbContext.Entry(entity).State = System.Data.EntityState.Modified;
            }
            //return _dbContext.SaveChanges();
            return entitys.Count();
        }

        /// <summary>
        /// 更新数据库中的多个实体
        /// </summary>
        /// <param name="commit">是否提交到数据库</param>
        /// <param name="entitys">更新的实体</param>
        /// <returns>执行结果受影响行数</returns>
        public virtual int Update(bool commit, params T[] entitys)
        {
            foreach (var entity in entitys)
            {
                _dbContext.Entry(entity).State = System.Data.EntityState.Modified;
            }
            //return _dbContext.SaveChanges();
            return commit ? _dbContext.SaveChanges() : entitys.Count();
        }

        /// <summary>
        /// 根据传入委托查询出存在条数
        /// </summary>
        /// <param name="where">筛选条件表达式</param>
        /// <returns>存在条数</returns>
        public virtual int SelectCount(Expression<Func<T, bool>> where)
        {
            return _dbContext.Set<T>().Count(where);
        }

        /// <summary>
        /// 根据传入委托筛选出对应的单个数据实体
        /// </summary>
        /// <param name="where">筛选条件表达式</param>
        /// <returns>查询到单个数据实体</returns>
        public virtual T SelectSingle(Expression<Func<T, bool>> where)
        {
            return _dbContext.Set<T>().FirstOrDefault(where);
        }

        /// <summary>
        /// 选取数据库中的实体集合
        /// </summary>
        /// <param name="where">筛选条件</param>
        /// <returns>实体集合</returns>
        public virtual IQueryable<T> Select(Expression<Func<T, bool>> where)
        {
            //return _dbContext.Set<T>().Where<T>(where).AsQueryable<T>();
            return _dbContext.Set<T>().Where(where).AsQueryable();
        }

        /// <summary>
        /// 分页选取数据库中的实体集合
        /// </summary>
        /// <typeparam name="F">排序字段类型</typeparam>
        /// <param name="pageIndex">当前页码</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="totalCount">总记录数</param>
        /// <param name="where">筛选条件</param>
        /// <param name="orderBy">排序条件</param>
        /// <param name="isDesc">是否降序排列</param>
        /// <returns>实体集合</returns>
        public virtual IQueryable<T> SelectPage<F>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, F>> orderBy, bool isDesc)
        {
            totalCount = _dbContext.Set<T>().Where<T>(where).Count<T>();
            if (isDesc)
                return _dbContext.Set<T>()
                        .Where<T>(where)
                        .OrderByDescending<T, F>(orderBy)
                        .Skip<T>(pageSize * (pageIndex - 1))
                        .Take<T>(pageSize)
                        .AsQueryable<T>();
            return _dbContext.Set<T>()
                    .Where<T>(@where)
                    .OrderBy<T, F>(orderBy)
                    .Skip<T>(pageSize * (pageIndex - 1))
                    .Take<T>(pageSize)
                    .AsQueryable<T>();
        }

        /// <summary>
        /// 执行一个非查询的T-SQL语句，返回受影响行数
        /// </summary>
        /// <param name="sql">T-SQL语句</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>受影响行数</returns>
        public virtual int ExcuteNonQuery(string sql, params object[] parameters)
        {
            return _dbContext.Database.ExecuteSqlCommand(sql, parameters);
        }

        /// <summary>
        /// 执行一个原始SQL查询，返回泛型类型迭代器
        /// </summary>
        /// <param name="sql">T-SQL语句</param>
        /// <param name="parameters">参数列表</param>
        /// <returns>泛型类型迭代器</returns>
        public virtual IEnumerable<T> SqlQuery(string sql, params object[] parameters)
        {
            return _dbContext.Database.SqlQuery<T>(sql, parameters);
        }

        /// <summary>
        /// 保存数据库的改变状态
        /// </summary>
        /// <returns>受影响行数</returns>
        public virtual int SaveChanges()
        {
            return _dbContext.SaveChanges();
        }
    }
}
